package handlers

import (
	"context"
	"github.com/xormplus/xorm"
	"github.com/zw2582/ginlib"
	"go.uber.org/zap"
	"learn.micro.service.product/models"
	"learn.micro.service.product/proto/product"
)

type ProductHandler struct {

}

func (this *ProductHandler) ProductAdd(ctx context.Context, req *product.ProductInfo, resp *product.AddResponse) error {

	ginlib.Logger.Info("product add start")
	productId, err := models.DB.Transaction(func(session *xorm.Session) (interface{}, error) {
		p := models.Product{
			Name:        req.Name,
			Sku:         req.Sku,
			Price:       req.Price,
			Description: req.Description,
		}
		_, err := session.Insert(&p)
		if err != nil {
			ginlib.Logger.Info("product add fail", zap.String("err", err.Error()))
			return nil, err
		}
		productId := p.Id

		for _, img := range req.Images {
			if _, err = session.Insert(&models.ProductImage{
				ProductId: productId,
				Name:      img.Name,
				Image:     img.Image,
				Code:      img.Code,
			}); err != nil {
				return nil, err
			}
		}

		for _, size := range req.Sizes {
			if _, err = session.Insert(&models.ProductSize{
				ProductId: productId,
				Name:      size.Name,
				Size:      size.Size,
				Code:      size.Code,
			}); err != nil {
				return nil, err
			}
		}

		if _, err = session.Insert(&models.ProductSeo{
			ProductId:      productId,
			SeoTitle:       req.Seo.SeoTitle,
			SeoKeyword:     req.Seo.SeoKeyword,
			SeoDescription: req.Seo.SeoDescription,
			SeoCode:        req.Seo.Code,
		}); err != nil {
			return nil, err
		}

		return productId, nil
	})

	if err != nil {
		ginlib.Logger.Error("add fail return")
		return err
	}

	resp.Id = productId.(int64)
	ginlib.Logger.Info("success")
	return nil
}

func (this *ProductHandler) ProductUpdate(ctx context.Context, req *product.ProductInfo, resp *product.Response) error{
	_, err := models.DB.ID(req.Id).Update(&models.Product{
		Name:        req.Name,
		Sku:         req.Sku,
		Price:       req.Price,
		Description: req.Description,
	})
	if err != nil {
		return err
	}
	resp.Msg = "update success"
	return nil
}

func (this *ProductHandler) ProductDel(ctx context.Context, req *product.DelRequest, resp *product.Response) error{
	_, err := models.DB.Transaction(func(session *xorm.Session) (interface{}, error) {
		if _, err := session.ID(req.Id).Delete(&models.Product{}); err != nil {
			return nil, err
		}
		if _, err := session.Where("product_id = ?", req.Id).Delete(&models.ProductImage{}); err != nil {
			return nil, err
		}
		if _, err := session.Where("product_id = ?", req.Id).Delete(&models.ProductSize{}); err != nil {
			return nil, err
		}
		if _, err := session.Where("product_id = ?", req.Id).Delete(&models.ProductSeo{}); err != nil {
			return nil, err
		}
		return nil, nil
	})
	if err != nil {
		return err
	}
	resp.Msg = "delete success"
	return nil
}

func (this *ProductHandler) ProductGetById(ctx context.Context, req *product.GetByIdRequest, resp *product.ProductInfo) error{
	pro, err := models.ProductGetById(req.Id)
	if err != nil {
		return err
	}
	sizes, err := models.ProductSizeFindByProductId(req.Id)
	if err != nil {
		return err
	}
	imgs, err := models.ProductImageFindByProductId(req.Id)
	if err != nil {
		return err
	}
	seo, err := models.ProductSeoGetByProductId(req.Id)
	if err != nil {
		return err
	}
	resp.Id = pro.Id
	resp.Name = pro.Name
	resp.Price = pro.Price
	resp.Sku = pro.Sku
	resp.Description = pro.Description
	resp.Seo.SeoTitle = seo.SeoTitle
	resp.Seo.SeoKeyword = seo.SeoKeyword
	resp.Seo.SeoDescription = seo.SeoDescription
	resp.Seo.Code = seo.SeoCode
	psizes := make([]*product.ProductSize, 0)
	for _, val := range sizes {
		psizes = append(psizes, &product.ProductSize{
			Id:   val.Id,
			Size: val.Size,
			Name: val.Name,
			Code: val.Code,
		})
	}
	pimages := make([]*product.ProductImage, 0)
	for _, val := range imgs {
		pimages = append(pimages, &product.ProductImage{
			Id:    val.Id,
			Name:  val.Name,
			Image: val.Image,
			Code:  val.Code,
		})
	}
	resp.Sizes = psizes
	resp.Images = pimages
	return nil
}

func (this *ProductHandler) ProductFindAll(ctx context.Context, req *product.FindAllRequest, resp *product.ProductAll) error{
	return nil
}